package com.bennyhuo.kotlin.meta

import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.MemberName
import com.squareup.kotlinpoet.buildCodeBlock
import java.io.File

/**
 * Created by benny.
 */

fun helloWorld() {
  // FileSpec 是 Kotlin 源文件的描述类
  FileSpec.builder(
    "com.bennyhuo.kotlin.meta",
    "HelloWorld.kt"
  )
    // 导入 Kotlin 默认的包，例如 koltin.collections
    .addKotlinDefaultImports(includeJvm = false, includeJs = false)
    // 添加文件注释
    .addFileComment("This is generated by KotlinPoet.")
    // 添加函数，这在 Java 当中对应于方法（method）
    .addFunction(
      FunSpec.builder("main")
        .addParameter("args", String::class, KModifier.VARARG)
        // 注意 KotlinPoet 的格式化符使用 % 引导，JavaPoet 当中使用 $
        .addStatement("println(%S)", "Hello World")
        .build()
    )
    .build()
    .writeTo(File("data"))
}

fun formatP() {

  val codeBlock = buildCodeBlock {
    // val text = "Hello World"
    addStatement("val text = %S", "Hello World")
    addStatement("println(%P)", "Say \$text")
//    // println("Say ${'$'}text")
//    .addStatement("println(%S)", "Say \$text")
  }

  println(codeBlock)

  val codeBlock2 = buildCodeBlock {
    addStatement("println(%P)", buildCodeBlock {
      val className = ClassName("com.bennyhuo.kotlin.meta", "User")
      add("%T(name = %S, age = %L)", className, "bennyhuo", 35)
    })
  }

  FileSpec.builder("a", "b")
    .addFunction(
      FunSpec.builder("c")
        .addCode(codeBlock2)
        .build()
    )
    .build().writeTo(System.out)


}

fun formatM() {
  buildCodeBlock {
    val memberName = MemberName(
      // 包名
      packageName = "com.bennyhuo.kotlin.utils",
      // 函数名（如果是属性，则为属性名）
      simpleName = "listToString",
      // 是否定义为扩展函数或属性
      isExtension = true
    )
    addStatement("val s = listOf(1, 2, 3).%M()", memberName)
  }.let {
    FileSpec.builder("a", "b")
      .addFunction(
        FunSpec.builder("c")
          .addCode(it)
          .build()
      )
      .addKotlinDefaultImports()
      .build().writeTo(System.out)
  }
}

fun controlFlow() {
  buildCodeBlock {
    addStatement("val status = getStatus()")
    beginControlFlow("while (status == 0)")
    addStatement("...")
    endControlFlow()
  }.let { println(it) }
}

fun lineWrap() {
  FileSpec.builder("com.bennyhuo.kotlin.meta", "a")
    .addFunction(
      FunSpec.builder("wrapLine")
        .addStatement(
          ("val text = \"KotlinPoet is a Kotlin and Java API for generating" +
            " .kt source files. Source file generation can be useful when " +
            "doing things such as annotation processing or interacting with " +
            "metadata files (e.g., database schemas, protocol formats). By " +
            "generating code, you eliminate the need to write boilerplate " +
            "while also keeping a single source of truth for the metadata.\"").replace(' ', '·')
        ).build()
    )
    .build()
    .let { println(it) }
}

fun main() {
  formatP()
  formatM()
  controlFlow()
  lineWrap()
}